package cate.game.role.res.guild.po.treasurehouse;

import cate.common.table.d.GDFunc;
import cate.common.table.d.GDGuild;
import cate.common.table.guild.treasurehouse.GuildTreasureHouseItemRow;
import cate.common.table.guild.treasurehouse.GuildWeekendRewardRow;
import cate.common.util.GameResult;
import cate.game.chat.ChatContentParam;
import cate.game.notice.NoticeParam;
import cate.game.res.MixRes;
import cate.game.role.res.guild.GuildFuncBase;
import cate.game.role.res.guild.po.GuildPO;
import cate.game.role.res.guild.po.treasurehouse.msg.GuildTreasureHouseResp;
import easy.java.dev.note.NoteClass;
import easy.java.dev.note.NoteField;
import cate.game.role.Role;
import org.apache.commons.collections4.CollectionUtils;

import java.util.*;

@NoteClass("公会宝库")
public class GuildTreasureHouse extends GuildFuncBase {
    @NoteField("宝库物品")
    public Map<Integer, GuildTreasureItem> itemMap;
    @NoteField("宝库日志列表")
    public GuildTreasureLogPO logPO;

    @Override
    public void initialize(GuildPO parent) {
        super.initialize(parent);
        if (logPO == null) {
            logPO = new GuildTreasureLogPO();
        }
        logPO.initialize(parent);
        if (itemMap == null) {
            itemMap = new HashMap<>();
        }
        itemMap.values().forEach(item -> item.initialize(funcDependent.getGuild()));
    }

    /**
     * 循环
     */
    public void tick() {
        boolean changed = false;
        for (GuildTreasureItem item : itemMap.values()) {
            boolean c = item.tick();
            changed = changed || c;
        }
        if (changed) {
            synchronized (this) {
                itemMap.entrySet().removeIf(e -> e.getValue().isEmpty());
            }
        }
    }

    /**
     * 找到公会宝库单个配置项物品
     *
     * @param tid            配置ID
     * @param createWhenNull 未找到时是否创建
     * @return 单个配置项
     */
    private GuildTreasureItem findItem(int tid, boolean createWhenNull) {
        synchronized (this) {
            GuildTreasureItem itemPO = itemMap.get(tid);
            if (!createWhenNull || itemPO != null) {
                return itemPO;
            }
            itemPO = new GuildTreasureItem(tid);
            itemPO.initialize(getFuncDependent().guild);
            itemMap.put(tid, itemPO);
            return itemPO;
        }
    }

    /**
     * 放入物品
     *
     * @param role   放入玩家
     * @param tid    配置ID
     * @param num    数量
     * @param funcId 放入功能ID
     * @return 放入结果
     */
    public GameResult<MixRes> putTreasureIn(Role role, int tid, int num, int funcId) {
        GameResult<MixRes> r = new GameResult<>();
        GuildTreasureHouseItemRow row = getGame().table.guildTreasureHouse.item.get(tid);
        if (row == null) {
            return r.fail("该物品不能放入宝库");
        }
        GuildTreasureItem itemPO = findItem(tid, true);
        if (itemPO == null) {
            return r.fail("未知错误");
        }
        GameResult<MixRes> r_add = itemPO.add(num, funcId);
        if (!r_add.ok()) {
            synchronized (this) {
                itemMap.entrySet().removeIf(e -> e.getValue().isEmpty());
            }
            return r.fail(r_add);
        }
        MixRes addRes = r_add.data;
        if (role != null) {
            // 个人放入日志
            addLog(NoticeParam.of(GDGuild.log.PUT_TREASURE_IN,
                    Arrays.asList(
                            ChatContentParam.c(ChatContentParam.TYPE_STRING, role.getBase().name),
                            ChatContentParam.c(ChatContentParam.TYPE_MIX_RES, addRes)
                    )
            ));
        } else {
            int noticeId = 0;
            switch (funcId) {
                case GDFunc.GuildFunc.TREASURE_HOUSE:
                    noticeId = GDGuild.log.SYSTEM_SEND_GIFT;
                    break;
                case GDFunc.GuildFunc.FAIRYLAND:
                    noticeId = GDGuild.log.FAIRYLAND_GIFT;
                    break;
                case GDFunc.GuildFunc.WAR:
                    noticeId = GDGuild.log.GUILD_WAR_GIFT;
                    break;
            }
            if (noticeId != 0) {
                addLog(NoticeParam.of(noticeId,
                        Collections.singletonList(ChatContentParam.c(ChatContentParam.TYPE_MIX_RES, addRes))
                ));
            }
        }
        r.data = new MixRes(row.rewardStr).multiply(num);
        noticeOnline();
        return r.success();
    }

    /**
     * 添加日志
     *
     * @param param 日志
     */
    private void addLog(NoticeParam param) {
        logPO.addLog(param);
    }

    /**
     * 取出宝库物品
     *
     * @param role 取出玩家
     * @param tid 配置ID
     * @param num 取出数量
     * @return 取出结果
     */
    public GameResult<MixRes> takeTreasureOut(Role role, int tid, int num) {
        GameResult<MixRes> r = new GameResult<>();
        GuildTreasureHouseItemRow row = getGame().table.guildTreasureHouse.item.get(tid);
        if (row == null) {
            return r.fail("找不到该物品");
        }
        GuildTreasureItem itemPO = findItem(tid, false);
        if (itemPO == null) {
            return r.fail("找不到该物品");
        }
        GameResult<MixRes> r_take = itemPO.reduce(num);
        if (!r_take.ok()) {
            return r.fail(r_take);
        }
        addLog(NoticeParam.of(GDGuild.log.TAKE_TREASURE_OUT,
                Arrays.asList(
                        ChatContentParam.c(ChatContentParam.TYPE_STRING, role.getBase().name),
                        ChatContentParam.c(ChatContentParam.TYPE_MIX_RES, r_take.data)
                )
        ));
        r.data = r_take.data;
        noticeOnline();
        return r.success();
    }

    /**
     * 跨天
     */
    public void onDaySpan() {
        logPO.onDaySpan();
    }

    /**
     * 跨周
     */
    public void onWeekSpan() {
        GuildPO guild = funcDependent.getGuild();
        List<GuildWeekendRewardRow> rewardList = guild.game.table.guildTreasureHouse.reward.onGetAllReward(guild.game.getOpenDay());
        if (CollectionUtils.isEmpty(rewardList)) {
            return;
        }
        for (GuildWeekendRewardRow row : rewardList) {
            putTreasureIn(null, row.tid, row.num, getFuncId());
        }
        noticeOnline();
    }

    /**
     * 通知在线玩家
     */
    private void noticeOnline() {
        funcDependent.guild.noticeOnline(member -> member.sendNow(new GuildTreasureHouseResp(member)));
    }

    @Override
    public int getFuncId() {
        return GDFunc.GuildFunc.TREASURE_HOUSE;
    }
}
